<?php 
/*
 * Webing - The SNS blog
 *
 * Copyright (c) 2009 Webing. All rights reserved.
 *
 * This is mysql class
 */

/*$Id: mysql.php 59 2009-08-10 10:20:43Z chopins.xiao $;*/

final class mysqldb
{
    /**
     * This is mysql connect resource
     *
     * @var resource
     */
    private $db_link;
    /**
     * This is lastest mysql query and return result resource
     *
     * @var resource
     */
    private $result;
    /**
     * This is save lastest query sql
     *
     * @var string
     */
    private $sql;
    /**
     * This is error tracker of this mysqldb class
     *
     * @var array
     */
    private $tracker = array();
    /**
     * This save name and password of all privileges user to database
     *
     * @var array
     */
    private $all_user = array();
    /**
     * This save name and password of read only user to database
     *
     * @var array
     */
    private $read_user = array();
    /**
     * construct read only user connect mysql
     *
     * @param string $host
     * @param string $user
     * @param string $passwd
     */
    public function __construct(string $host = null, string $user = null, string $passwd = null)
    {
        $this->tracker[__LINE__ - 1] = __METHOD__;
        if($user != null)
        {
            $this->read_user['user'] = $user;
            $this->read_user['passwd'] = $passwd;
        }
        if($host != null)
        {
            $this->connect($host);
        }
    }
    /**
     * select dbname methods
     *
     * @param string $dbname
     */
    public function set_dbname(string $dbname)
    {
        $this->tracker[__LINE__ -1] = __METHOD__;
        if(!@mysql_select_db($dbname, $this->db_link))
        {
            $this->db_error();
        }
    }
    /**
     * Set all privileges user for database
     *
     * @param string $user
     * @param string $passwd
     */
    public function set_user(string $user, string $passwd)
    {
        $this->tracker[__LINE__ -1] = __METHOD__;
        $this->all_user['user'] = $user;
        $this->all_user['passwd'] = $passwd;
    }
    /**
     * Set read only user for database
     *
     * @param string $user
     * @param string $passwd
     */
    public function set_read_user(string $user, string $passwd)
    {
        $this->tracker[__LINE__ -1] = __METHOD__;
        $this->read_user['user'] = $user;
        $this->read_user['passwd'] = $passwd;
    }
    /**
     * The methods action what connect mysql
     *
     * @param bool $readonly
     * @param bool $pconnect
     */
    public function connect(bool $readonly = true, bool $pconnect = false)
    {
        $this->tracker[__LINE__ -1] = __METHOD__;
        if($readonly)
        {
            $user = $this->read_user['user'];
            $passwd = $this->read_user['passwd'];
        }else{
            $user = $this->all_user['user'];
            $passwd = $this->all_user['passwd'];
        }
        if($pconnect)
        {
            $this->db_link = @mysql_pconnect($this->host, $user, $passwd);
        }else{
            $this->db_link = @mysql_connect($this->host, $user, $passwd);
        }
        if(!$this->db_link)
        {
            $this->db_error();
        }
    }
    /**
     * Send sql query to mysql
     *
     * @param string $sql
     * @param bool $unbuff
     */
    private function query(string $sql, bool $unbuff = false)
    {
        $this->tracker[__LINE__ -1] = __METHOD__;
        if($unbuff)
        {
            $this->result = mysql_unbuffered_query($sql, $this->db_link);
        }else{
            $this->result = mysql_query($sql, $this->db_link);
        }
        if(!$this->result)
        {
            $this->db_error();
        }
    }
    /**
     * Execute insert, update, delete to database
     *
     * @param string $sql
     * @param bool $return_insert
     * @return integer or bool
     */
    public function execute(string $sql, bool $return_insert = false)
    {
        $this->tracker[__LINE__ -1] = __METHOD__;
        $sql = trim($sql);
        $part = in_array(strtoupper(substr($sql, 0, 6)), array('INSERT', 'UPDATE', 'DELETE')); 
        if(!$part)
        {
            return FALSE;
        }
        $this->query($sql);
        if($return_insert)
        {
            return $this->insert_id();
        }
        return TRUE;
    }
    /**
     * Return last insert id
     *
     * @return integer
     */
    public function insert_id()
    {
        $this->tracker[__LINE__ -1] = __METHOD__;
        return $this->getOne('SELECT LAST_INSERT_ID()');
    }
    /**
     * Return auto increment for table
     *
     * @param string $table
     * @return integer
     */
    public function auto_id(string $table)
    {
        $this->tracker[__LINE__ - 1] = __METHOD__;
        $status = $this->getRow("SHOW TABLE STATUS WHERE Name='$table'");
        return $status['Auto_increment'];
    }
    /**
     * Get one field of one row result
     *
     * @param string $sql
     * @return integer or string
     */
    public function getOne(string $sql)
    {
        $this->tracker[__LINE__ - 1] = __METHOD__;
        $this->sql = $sql;
        $sql = trim($sql, ';');
        if(strtoupper(substr($sql, 0, 6)) == 'SELECT')
        {
            if(!preg_match('/LIMIT/i', '$sql'))
            {
                $sql .= 'LIMIT 1';
            }
        }
        $this->query($sql);
        $row = mysql_fetch_row($this->result);
        mysql_free_result($this->result);
        return $row[0];
    }
    /**
     * Get one row result
     *
     * @param string $sql
     * @return array
     */
    public function getRow(string $sql)
    {
        $this->tracker[__LINE__ - 1] = __METHOD__;
        $this->sql = $sql;
        $sql = trim($sql, ';');
        if(strtoupper(substr($sql, 0, 6)) == 'SELECT')
        {
            if(!preg_match('/LIMIT/i', '$sql'))
            {
                $sql .= 'LIMIT 1';
            }
        }
        $this->qury($sql, true);
        return mysql_fetch_array($this->result);
    }
    /**
     * Get all result to one array
     *
     * @param string $sql
     * @return array
     */
    public function getAll(string $sql)
    {
        $this->tracker[__LINE__ - 1] = __METHOD__;
        $this->sql = $sql;
        $this->query($sql);
        $return = array();
        while($row = mysql_fetch_assoc($this->result))
        {
            $return[] = $row;
        }
        return $return;
    }
    /**
     * Get all result and apply a user function to every field of every row
     *
     * @param string $sql
     * @param mix $func2assoc
     * @return array
     */
    public function func2result(string $sql,mixed $func2assoc)
    {
        $this->tracker[__LINE__ - 1] = __METHOD__;
        $this->sql = $sql;
        $this->query($sql);
        if(is_string($func2assoc))
        {
            $this->tracker[__LINE__ - 1] = 'function to all';
            while($row = mysql_fetch_assoc($this->result))
            {
                foreach($row as $key => $var)
                {
                    $re_row[$key] = $func2assoc($var);
                }
                $return[] = $re_row;
            }
            return $return;
        }elseif(is_array($func2assoc))
        {
            $this->tracker[__LINE__ - 1] = 'functon to list';
            while($row = mysql_fetch_assoc($this->result))
            {
                foreach($row as $key => $var)
                {
                    $re_row[$key] = $func2assoc[$key]($var);
                }
                $return[] = $re_row;
            }
            return $return;
        }else{
            return FALSE;
        }
                    
    }
    /**
     * Mysql retrun error 
     *
     * @param integer $line
     * @return unknown
     */
    private function db_error(integer $line)
    {
        $error_msg['mysql_error_no'] = mysql_errno($this->db_link);
        $error_msg['mysql_error'] = mysql_error($this->db_link);
        $error_msg['error_name'] = 'MySQL Error';
        $error_msg['FILE'] = __FILE__;
        $error_msg['sql'] = $this->sql;
        $error_msg['TRACKER'] = $this->tracker;
        $error_msg['LEVEL'] = '1';
        $err = serialize($error_msg);
        trigger_error($err);
    }
    private function __destruct()
    {
        unset($this->tracker);
        mysql_free_result($this->result);
        mysql_close($this->db_link);
    }
    
}
